package compilers.compiler;

import java.io.FileOutputStream;
import java.io.PrintStream;

public class PGenerator {
	
	private PrintStream fPStream;
	
	public PGenerator(String fileName) throws Exception {
		try {
			FileOutputStream out =  new FileOutputStream(fileName);
			fPStream = new PrintStream(out);
			fPStream.println("ldc i 0");
			fPStream.println("ldc i 0");
			fPStream.println("ldc c 0");
		} catch (Exception e) {
			throw e;
		}
	}
	
	public void finish() {
		fPStream.println("startOfProgram:");
		fPStream.println("mst 0");
		fPStream.println("cup 0 begin_main");
		fPStream.println("hlt");
		fPStream.close();
	}
	
	public void load(char type, String value) {
		if(type == 'c') {
			if(value.length() == 1) {
				fPStream.println("ldc " + type + " " + "'" + value + "'");
			} else {
				fPStream.println("ldc " + type + " " + value);
			}
		} else {
			fPStream.println("ldc " + type + " " + value);
		}
	}
	
	public void loadFromAddress(char type, int address) {
		fPStream.println("ldo " + type + " " + address);
	}
	
	public void storeAtAddress(char type, int address) {
		fPStream.println("sro " + type + " " + address);
	}
	
	public void not() {
		fPStream.println("not");
	}
	
	public void and() {
		fPStream.println("and");
	}
	
	public void or() {
		fPStream.println("or");
	}
	
	public void negate(char type) {
		fPStream.println("neg " + type);
	}
	
	public void mult(char type) {
		fPStream.println("mul " + type);
	}
	
	public void div(char type) {
		fPStream.println("div " + type);
	}
	
	public void add(char type) {
		fPStream.println("add " + type);
	}
	
	public void sub(char type) {
		fPStream.println("sub " + type);
	}
	
	public void equalsRel(char type) {
		fPStream.println("equ " + type);
	}
	
	public void nEquals(char type) {
		fPStream.println("neq " + type);
	}
	
	public void less(char type) {
		fPStream.println("les " + type);
	}
	
	public void lessEq(char type) {
		fPStream.println("leq " + type);
	}
	
	public void greater(char type) {
		fPStream.println("grt " + type);
	}
	
	public void greaterEq(char type) {
		fPStream.println("geq " + type);
	}
	
	public void newMem() {
		fPStream.println("new");
	}
	
	public void beginLabel(String lbl) {
		fPStream.println("begin_" + lbl + ":");
	}
	
	public void endLabel(String lbl) {
		fPStream.println("end_" + lbl + ":");
	}
	
	public void ssp(int memElements) {
		fPStream.println("ssp " + Integer.toString(memElements));
	}
	
	public void retf() {
		fPStream.println("retf");
	}
	
	public void str(char type, int depth, int address) {
		fPStream.println("str " + type + " " + Integer.toString(depth) + " " + Integer.toString(address));
	}
	
	public void lod(char type, int depth, int address) {
		fPStream.println("lod " + type + " " + Integer.toString(depth) + " " + Integer.toString(address));
	}

	public void conditionalJump(String label) {
		fPStream.println("fjp " + label);
	}
	
	public void unconditionalJump(String label) {
		fPStream.println("ujp " + label);
	}
	
	public void ujp(String label) {
		fPStream.println("ujp " + label);
	}
	
	public void goToStart() {
		this.ujp("startOfProgram");
	}
	
	public void out(char type) {
		fPStream.println("out " + type);
	}
	
	public void mst(int depth) {
		fPStream.println("mst " + Integer.toString(depth));
	}
	
	public void cup(int parameters, String label) {
		fPStream.println("cup " + Integer.toString(parameters) + " " + label);
	}
	
	public void in(char type) {
		fPStream.println("in " + type);
	}
	
	public void conv(char from, char to) {
		fPStream.println("conv " + from + " " + to);
	}
	
	public void inc(char type, int value) {
		fPStream.println("inc " + type + " " + Integer.toString(value));
	}
	
	public void lda(int depth, int address) {
		fPStream.println("lda " + Integer.toString(depth) + " " + Integer.toString(address));
	}
	
	public void movs(int q) {
		fPStream.println("movs " + Integer.toString(q));
	}
	
	public void sto(char type) {
		fPStream.println("sto " + type);
	}
}
